home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / daemons / inetd / RCS / inetd.c,v < prev   
Encoding:
Text File  |  1991-10-17  |  26.2 KB  |  1,295 lines

  1. head     1.12;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    shirriff:1.12; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.12
  10. date     90.09.24.14.41.44;  author douglis;  state Exp;
  11. branches ;
  12. next     1.11;
  13.  
  14. 1.11
  15. date     90.04.12.20.46.01;  author douglis;  state Exp;
  16. branches ;
  17. next     1.10;
  18.  
  19. 1.10
  20. date     90.02.16.12.55.11;  author douglis;  state Exp;
  21. branches ;
  22. next     1.9;
  23.  
  24. 1.9
  25. date     89.07.31.17.48.49;  author douglis;  state Exp;
  26. branches ;
  27. next     1.8;
  28.  
  29. 1.8
  30. date     89.06.16.00.39.37;  author douglis;  state Exp;
  31. branches ;
  32. next     1.7;
  33.  
  34. 1.7
  35. date     88.12.22.17.41.26;  author ouster;  state Exp;
  36. branches ;
  37. next     1.6;
  38.  
  39. 1.6
  40. date     88.09.28.12.11.48;  author mendel;  state Exp;
  41. branches ;
  42. next     1.5;
  43.  
  44. 1.5
  45. date     88.08.15.16.01.29;  author mendel;  state Exp;
  46. branches ;
  47. next     1.4;
  48.  
  49. 1.4
  50. date     88.02.21.15.59.53;  author douglis;  state Exp;
  51. branches ;
  52. next     1.3;
  53.  
  54. 1.3
  55. date     87.08.28.19.02.12;  author andrew;  state Exp;
  56. branches ;
  57. next     1.2;
  58.  
  59. 1.2
  60. date     87.08.27.20.06.14;  author andrew;  state Exp;
  61. branches ;
  62. next     1.1;
  63.  
  64. 1.1
  65. date     87.07.19.23.19.05;  author andrew;  state Exp;
  66. branches ;
  67. next     ;
  68.  
  69.  
  70. desc
  71. @original version from 4.3BSD
  72. @
  73.  
  74.  
  75. 1.12
  76. log
  77. @fixes for error in recvfrom
  78. @
  79. text
  80. @/*
  81.  * Copyright (c) 1983 Regents of the University of California.
  82.  * All rights reserved.
  83.  *
  84.  * Redistribution and use in source and binary forms are permitted
  85.  * provided that this notice is preserved and that due credit is given
  86.  * to the University of California at Berkeley. The name of the University
  87.  * may not be used to endorse or promote products derived from this
  88.  * software without specific prior written permission. This software
  89.  * is provided ``as is'' without express or implied warranty.
  90.  */
  91.  
  92. #ifndef lint
  93. char copyright[] =
  94. "@@(#) Copyright (c) 1983 Regents of the University of California.\n\
  95.  All rights reserved.\n";
  96. #endif not lint
  97.  
  98. #ifndef lint
  99. static char sccsid[] = "@@(#)inetd.c    5.7 (Berkeley) 8/19/86";
  100. #endif not lint
  101.  
  102. /*
  103.  * Inetd - Internet super-server
  104.  *
  105.  * This program invokes all internet services as needed.
  106.  * connection-oriented services are invoked each time a
  107.  * connection is made, by creating a process.  This process
  108.  * is passed the connection as file descriptor 0 and is
  109.  * expected to do a getpeername to find out the source host
  110.  * and port.
  111.  *
  112.  * Datagram oriented services are invoked when a datagram
  113.  * arrives; a process is created and passed a pending message
  114.  * on file descriptor 0.  Datagram servers may either connect
  115.  * to their peer, freeing up the original socket for inetd
  116.  * to receive further messages on, or ``take over the socket'',
  117.  * processing all arriving datagrams and, eventually, timing
  118.  * out.     The first type of server is said to be ``multi-threaded'';
  119.  * the second type of server ``single-threaded''. 
  120.  *
  121.  * Inetd uses a configuration file which is read at startup
  122.  * and, possibly, at some later time in response to a hangup signal.
  123.  * The configuration file is ``free format'' with fields given in the
  124.  * order shown below.  Continuation lines for an entry must being with
  125.  * a space or tab.  All fields must be present in each entry.
  126.  *
  127.  *    service name            must be in /etc/services
  128.  *    socket type            stream/dgram/raw/rdm/seqpacket
  129.  *    protocol            must be in /etc/protocols
  130.  *    wait/nowait            single-threaded/multi-threaded
  131.  *    user                user to run daemon as
  132.  *    server program            full path name
  133.  *    server program arguments    maximum of MAXARGS (5)
  134.  *
  135.  * Comment lines are indicated by a `#' in column 1.
  136.  */
  137. #include <sys/param.h>
  138. #include <sys/stat.h>
  139. #include <sys/socket.h>
  140. #include <sys/file.h>
  141. #include <sys/wait.h>
  142. #include <sys/time.h>
  143. #include <sys/resource.h>
  144.  
  145. #include <netinet/in.h>
  146. #include <arpa/inet.h>
  147.  
  148. #include <errno.h>
  149. #include <stdio.h>
  150. #include <signal.h>
  151. #include <netdb.h>
  152. #include <syslog.h>
  153. #include <pwd.h>
  154.  
  155.  
  156. #define    TOOMANY        40        /* don't start more than TOOMANY */
  157. #define    CNT_INTVL    60        /* servers in CNT_INTVL sec. */
  158. #define    RETRYTIME    (60*10)        /* retry after bind or server fail */
  159.  
  160. #define    SIGBLOCK    (sigmask(SIGCHLD)|sigmask(SIGHUP)|sigmask(SIGALRM))
  161.  
  162. extern    int errno;
  163.  
  164. void    reapchild(), retry(), config();
  165. char    *index();
  166. char    *malloc();
  167.  
  168. int    debug = 0;
  169. int    nsock, maxsock;
  170. fd_set    allsock;
  171. int    options;
  172. int    timingout;
  173. struct    servent *sp;
  174.  
  175. struct    servtab {
  176.     char    *se_service;        /* name of service */
  177.     int    se_socktype;        /* type of socket to use */
  178.     char    *se_proto;        /* protocol used */
  179.     int      se_wait;        /* single threaded server */
  180.     int      se_checked;        /* looked at during merge */
  181.     char    *se_user;        /* user name to run as */
  182.     struct    biltin *se_bi;        /* if built-in, description */
  183.     char    *se_server;        /* server program */
  184. #define MAXARGV 5
  185.     char    *se_argv[MAXARGV+1];    /* program arguments */
  186.     int    se_fd;            /* open descriptor */
  187.     struct    sockaddr_in se_ctrladdr;/* bound address */
  188.     int    se_count;        /* number started since se_time */
  189.     struct    timeval se_time;    /* start of se_count */
  190.     struct    servtab *se_next;
  191. } *servtab;
  192.  
  193. int echo_stream(), discard_stream(), machtime_stream();
  194. int daytime_stream(), chargen_stream();
  195. int echo_dg(), discard_dg(), machtime_dg(), daytime_dg(), chargen_dg();
  196.  
  197. struct biltin {
  198.     char    *bi_service;        /* internally provided service name */
  199.     int    bi_socktype;        /* type of socket supported */
  200.     int      bi_fork;        /* 1 if should fork before call */
  201.     int      bi_wait;        /* 1 if should wait for child */
  202.     int    (*bi_fn)();        /* function which performs it */
  203. } biltins[] = {
  204.     /* Echo received data */
  205.     "echo",        SOCK_STREAM,    1, 0,    echo_stream,
  206.     "echo",        SOCK_DGRAM,    0, 0,    echo_dg,
  207.  
  208.     /* Internet /dev/null */
  209.     "discard",    SOCK_STREAM,    1, 0,    discard_stream,
  210.     "discard",    SOCK_DGRAM,    0, 0,    discard_dg,
  211.  
  212.     /* Return 32 bit time since 1970 */
  213.     "time",        SOCK_STREAM,    0, 0,    machtime_stream,
  214.     "time",        SOCK_DGRAM,    0, 0,    machtime_dg,
  215.  
  216.     /* Return human-readable time */
  217.     "daytime",    SOCK_STREAM,    0, 0,    daytime_stream,
  218.     "daytime",    SOCK_DGRAM,    0, 0,    daytime_dg,
  219.  
  220.     /* Familiar character generator */
  221.     "chargen",    SOCK_STREAM,    1, 0,    chargen_stream,
  222.     "chargen",    SOCK_DGRAM,    0, 0,    chargen_dg,
  223.     0
  224. };
  225.  
  226. #define NUMINT    (sizeof(intab) / sizeof(struct inent))
  227. char    *CONFIG = "/sprite/daemons/inetd.conf";
  228. char    **Argv;
  229. char     *LastArg;
  230.  
  231. main(argc, argv, envp)
  232.     int argc;
  233.     char *argv[], *envp[];
  234. {
  235.     register struct servtab *sep;
  236.     register struct passwd *pwd;
  237.     char *cp, buf[50];
  238.     int pid, i, dofork;
  239.     struct sigvec sv;
  240.     int       selectErrors = 0;
  241.     char *childEnv[4];
  242.     char **childEnvPtr = childEnv;
  243.     char **envPtr;
  244.     extern char **environ;
  245.  
  246.  
  247.     /*
  248.      * Get the "true" environment and pull out the variables
  249.      * we want to pass to our children.
  250.      */
  251.     for (envPtr = environ; *envPtr != NULL; envPtr++) {
  252.         if (!strncmp(*envPtr, "MACHINE=", strlen("MACHINE=")) ||
  253.         !strncmp(*envPtr, "SPRITE_OS=", strlen("SPRITE_OS=")) ||
  254.         !strncmp(*envPtr, "HOME=", strlen("HOME="))) {
  255.         *childEnvPtr = *envPtr;
  256.         childEnvPtr++;
  257.         }
  258.     }
  259.  
  260.     *childEnvPtr = NULL;
  261.  
  262.     /*
  263.      * Make sure our real uid is root.  This also makes sure we were
  264.      * at least invoked with an effective uid of root.
  265.      */
  266.     if (setreuid(0, 0) < 0) {
  267.         perror("setreuid");
  268.     }
  269.     
  270.     Argv = argv;
  271.     if (envp == 0 || *envp == 0)
  272.         envp = argv;
  273.     while (*envp)
  274.         envp++;
  275.     LastArg = envp[-1] + strlen(envp[-1]);
  276.     argc--, argv++;
  277.     while (argc > 0 && *argv[0] == '-') {
  278.         for (cp = &argv[0][1]; *cp; cp++) switch (*cp) {
  279.  
  280.         case 'd':
  281.             debug = 1;
  282.             options |= SO_DEBUG;
  283.             break;
  284.  
  285.         default:
  286.             fprintf(stderr,
  287.                 "inetd: Unknown flag -%c ignored.\n", *cp);
  288.             break;
  289.         }
  290. nextopt:
  291.         argc--, argv++;
  292.     }
  293.     if (argc > 0)
  294.         CONFIG = argv[0];
  295.     if (!debug) {
  296.         if (fork())
  297.             exit(0);
  298.         { int s;
  299.         for (s = 0; s < 10; s++)
  300.             (void) close(s);
  301.         }
  302.         (void) open("/", O_RDONLY);
  303.         (void) dup2(0, 1);
  304.         (void) dup2(0, 2);
  305.     }
  306.     openlog("inetd", LOG_PID | LOG_NOWAIT, LOG_DAEMON);
  307.     bzero((char *)&sv, sizeof(sv));
  308.     sv.sv_mask = SIGBLOCK;
  309.     sv.sv_handler = retry;
  310.     sigvec(SIGALRM, &sv, (struct sigvec *)0);
  311.     config();
  312.     sv.sv_handler = config;
  313.     sigvec(SIGHUP, &sv, (struct sigvec *)0);
  314.     sv.sv_handler = reapchild;
  315.     sigvec(SIGCHLD, &sv, (struct sigvec *)0);
  316.  
  317.  
  318.     for (;;) {
  319.         int s, ctrl, n, errorCount;
  320.         fd_set readable;
  321.  
  322.         while (nsock == 0)
  323.             sigpause(0);
  324.         readable = allsock;
  325.         if ((n = select(maxsock + 1, &readable, (fd_set *)0,
  326.         (fd_set *)0, (struct timeval *)0)) <= 0) {
  327.             if (n < 0 && errno != EINTR) {
  328.             syslog(LOG_WARNING, "select: %m\n");
  329.             selectErrors++;
  330.             if (selectErrors > 25) {
  331.                 syslog(LOG_ERR,
  332.                     "Exiting: Too many select errors\n");
  333.                 exit(1);
  334.             }
  335.             }
  336.             sleep(1);
  337.             continue;
  338.         }
  339.         errorCount = n;
  340.         for (sep = servtab; n && sep; sep = sep->se_next)
  341.         if (sep->se_fd != -1 && FD_ISSET(sep->se_fd, &readable)) {
  342.         n--;
  343.         if (debug)
  344.             fprintf(stderr, "someone wants %s\n", sep->se_service);
  345.         if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) {
  346.             ctrl = accept(sep->se_fd, (struct sockaddr *)0,
  347.                 (int *)0);
  348.             if (debug)
  349.                 fprintf(stderr, "accept, ctrl %d\n", ctrl);
  350.             if (ctrl < 0) {
  351.                 if (errno == EINTR)
  352.                     continue;
  353.                 syslog(LOG_WARNING, "%s/%s accept: %m",
  354.                         sep->se_service, sep->se_proto);
  355.                 FD_CLR(sep->se_fd, &allsock);
  356.                 nsock--;
  357.                 (void) close(sep->se_fd);
  358.                 sep->se_fd = -1;
  359.                 continue;
  360.             }
  361.         } else
  362.             ctrl = sep->se_fd;
  363.         (void) sigblock(SIGBLOCK);
  364.         pid = 0;
  365.         dofork = (sep->se_bi == 0 || sep->se_bi->bi_fork);
  366.         if (dofork) {
  367.             if (debug) 
  368.                 fprintf(stderr, "doing fork\n");
  369.             if (sep->se_count++ == 0)
  370.                 (void)gettimeofday(&sep->se_time,
  371.                     (struct timezone *)0);
  372.             else if (sep->se_count >= TOOMANY) {
  373.                 struct timeval now;
  374.  
  375.                 (void)gettimeofday(&now, (struct timezone *)0);
  376.                 if (now.tv_sec - sep->se_time.tv_sec >
  377.                     CNT_INTVL) {
  378.                     sep->se_time = now;
  379.                     sep->se_count = 1;
  380.                 } else {
  381.                     syslog(LOG_ERR,
  382.             "%s/%s server failing (looping), service terminated\n",
  383.                         sep->se_service, sep->se_proto);
  384.                     FD_CLR(sep->se_fd, &allsock);
  385.                     (void) close(sep->se_fd);
  386.                     sep->se_fd = -1;
  387.                     sep->se_count = 0;
  388.                     nsock--;
  389.                     sigsetmask(0);
  390.                     if (!timingout) {
  391.                         timingout = 1;
  392.                         alarm(RETRYTIME);
  393.                     }
  394.                     continue;
  395.                 }
  396.             }
  397.             pid = fork();
  398.         }
  399.         if (pid < 0) {
  400.             if (!sep->se_wait && sep->se_socktype == SOCK_STREAM)
  401.                 close(ctrl);
  402.             sigsetmask(0);
  403.             sleep(1);
  404.             continue;
  405.         }
  406.         if (pid && sep->se_wait) {
  407.             sep->se_wait = pid;
  408.             FD_CLR(sep->se_fd, &allsock);
  409.             nsock--;
  410.         }
  411.         sigsetmask(0);
  412.         if (pid == 0) {
  413.             if (dofork)
  414.                 for (i = getdtablesize(); --i > 2; )
  415.                     if (i != ctrl)
  416.                         close(i);
  417.             if (sep->se_bi)
  418.                 (*sep->se_bi->bi_fn)(ctrl, sep);
  419.             else {
  420.                 dup2(ctrl, 0);
  421.                 close(ctrl);
  422.                 dup2(0, 1);
  423.                 dup2(0, 2);
  424.                 if ((pwd = getpwnam(sep->se_user)) == NULL) {
  425.                     syslog(LOG_ERR,
  426.                         "getpwnam: %s: No such user",
  427.                         sep->se_user);
  428.                     if (sep->se_socktype != SOCK_STREAM)
  429.                         recv(0, buf, sizeof (buf), 0);
  430.                     _exit(1);
  431.                 }
  432.                 if (pwd->pw_uid) {
  433.                     (void) setgid((gid_t)pwd->pw_gid);
  434.                     initgroups(pwd->pw_name, pwd->pw_gid);
  435.                     (void) setuid((uid_t)pwd->pw_uid);
  436.                 }
  437.                 if (debug)
  438.                     syslog(LOG_INFO, "execl %s",
  439.                         sep->se_server);
  440.                 execve(sep->se_server, sep->se_argv, childEnv);
  441.                 if (sep->se_socktype != SOCK_STREAM)
  442.                     recv(0, buf, sizeof (buf), 0);
  443.                 syslog(LOG_ERR, "execv %s: %m", sep->se_server);
  444.                 _exit(1);
  445.             }
  446.         }
  447.         if (!sep->se_wait && sep->se_socktype == SOCK_STREAM)
  448.             close(ctrl);
  449.         }
  450.     }
  451. }
  452.  
  453. void
  454. reapchild()
  455. {
  456.     union wait status;
  457.     int pid;
  458.     register struct servtab *sep;
  459.  
  460.     if (debug)
  461.         fprintf(stderr, "entering reapchild()\n");
  462.     for (;;) {
  463.         pid = wait3(&status, WNOHANG, (struct rusage *)0);
  464.         if (pid <= 0)
  465.             break;
  466.         if (debug)
  467.             fprintf(stderr, "%d reaped\n", pid);
  468.         for (sep = servtab; sep; sep = sep->se_next)
  469.             if (sep->se_wait == pid) {
  470.                 if (status.w_status)
  471.                     syslog(LOG_WARNING,
  472.                         "%s: exit status 0x%x",
  473.                         sep->se_server, status);
  474.                 if (debug)
  475.                     fprintf(stderr, "restored %s, fd %d\n",
  476.                         sep->se_service, sep->se_fd);
  477.                 FD_SET(sep->se_fd, &allsock);
  478.                 nsock++;
  479.                 sep->se_wait = 1;
  480.             }
  481.     }
  482.     if (debug)
  483.         fprintf(stderr, "leaving reapchild()\n");
  484. }
  485.  
  486. void
  487. config()
  488. {
  489.     register struct servtab *sep, *cp, **sepp;
  490.     struct servtab *getconfigent(), *enter();
  491.     int omask;
  492.  
  493.     if (!setconfig()) {
  494.         syslog(LOG_ERR, "%s: %m", CONFIG);
  495.         return;
  496.     }
  497.     for (sep = servtab; sep; sep = sep->se_next)
  498.         sep->se_checked = 0;
  499.     while (cp = getconfigent()) {
  500.         for (sep = servtab; sep; sep = sep->se_next)
  501.             if (strcmp(sep->se_service, cp->se_service) == 0 &&
  502.                 strcmp(sep->se_proto, cp->se_proto) == 0)
  503.                 break;
  504.         if (sep != 0) {
  505.             int i;
  506.  
  507.             omask = sigblock(SIGBLOCK);
  508.             if (cp->se_bi == 0)
  509.                 sep->se_wait = cp->se_wait;
  510. #define SWAP(a, b) { char *c = a; a = b; b = c; }
  511.             if (cp->se_user)
  512.                 SWAP(sep->se_user, cp->se_user);
  513.             if (cp->se_server)
  514.                 SWAP(sep->se_server, cp->se_server);
  515.             for (i = 0; i < MAXARGV; i++)
  516.                 SWAP(sep->se_argv[i], cp->se_argv[i]);
  517.             sigsetmask(omask);
  518.             freeconfig(cp);
  519.             if (debug)
  520.                 print_service("REDO", sep);
  521.         } else {
  522.             sep = enter(cp);
  523.             if (debug)
  524.                 print_service("ADD ", sep);
  525.         }
  526.         sep->se_checked = 1;
  527.         sp = getservbyname(sep->se_service, sep->se_proto);
  528.         if (sp == 0) {
  529.             syslog(LOG_ERR, "%s/%s: unknown service",
  530.                 sep->se_service, sep->se_proto);
  531.             continue;
  532.         }
  533.         if (sp->s_port != sep->se_ctrladdr.sin_port) {
  534.             sep->se_ctrladdr.sin_port = sp->s_port;
  535.             if (sep->se_fd != -1)
  536.                 (void) close(sep->se_fd);
  537.             sep->se_fd = -1;
  538.         }
  539.         if (sep->se_fd == -1)
  540.             setup(sep);
  541.     }
  542.     endconfig();
  543.     /*
  544.      * Purge anything not looked at above.
  545.      */
  546.     omask = sigblock(SIGBLOCK);
  547.     sepp = &servtab;
  548.     while (sep = *sepp) {
  549.         if (sep->se_checked) {
  550.             sepp = &sep->se_next;
  551.             continue;
  552.         }
  553.         *sepp = sep->se_next;
  554.         if (sep->se_fd != -1) {
  555.             FD_CLR(sep->se_fd, &allsock);
  556.             nsock--;
  557.             (void) close(sep->se_fd);
  558.         }
  559.         if (debug)
  560.             print_service("FREE", sep);
  561.         freeconfig(sep);
  562.         free((char *)sep);
  563.     }
  564.     (void) sigsetmask(omask);
  565. }
  566.  
  567. void
  568. retry()
  569. {
  570.     register struct servtab *sep;
  571.  
  572.     timingout = 0;
  573.     for (sep = servtab; sep; sep = sep->se_next)
  574.         if (sep->se_fd == -1)
  575.             setup(sep);
  576. }
  577.  
  578. setup(sep)
  579.     register struct servtab *sep;
  580. {
  581.     int on = 1;
  582.  
  583.     if ((sep->se_fd = socket(AF_INET, sep->se_socktype, 0)) < 0) {
  584.         syslog(LOG_ERR, "%s/%s: socket: %m",
  585.             sep->se_service, sep->se_proto);
  586.         return;
  587.     }
  588. #define    turnon(fd, opt) \
  589. setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on))
  590.     if (strcmp(sep->se_proto, "tcp") == 0 && (options & SO_DEBUG) &&
  591.         turnon(sep->se_fd, SO_DEBUG) < 0)
  592.         syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m");
  593.     if (turnon(sep->se_fd, SO_REUSEADDR) < 0)
  594.         syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m");
  595. #undef turnon
  596.     if (bind(sep->se_fd, &sep->se_ctrladdr,
  597.         sizeof (sep->se_ctrladdr)) < 0) {
  598.         syslog(LOG_ERR, "%s/%s: bind: %m",
  599.             sep->se_service, sep->se_proto);
  600.         (void) close(sep->se_fd);
  601.         sep->se_fd = -1;
  602.         if (!timingout) {
  603.             timingout = 1;
  604.             alarm(RETRYTIME);
  605.         }
  606.         return;
  607.     }
  608.     if (sep->se_socktype == SOCK_STREAM)
  609.         listen(sep->se_fd, 10);
  610.     FD_SET(sep->se_fd, &allsock);
  611.     nsock++;
  612.     if (sep->se_fd > maxsock)
  613.         maxsock = sep->se_fd;
  614. }
  615.  
  616. struct servtab *
  617. enter(cp)
  618.     struct servtab *cp;
  619. {
  620.     register struct servtab *sep;
  621.     int omask;
  622.     char *strdup();
  623.  
  624.     sep = (struct servtab *)malloc(sizeof (*sep));
  625.     if (sep == (struct servtab *)0) {
  626.         syslog(LOG_ERR, "Out of memory.");
  627.         exit(-1);
  628.     }
  629.     *sep = *cp;
  630.     sep->se_fd = -1;
  631.     omask = sigblock(SIGBLOCK);
  632.     sep->se_next = servtab;
  633.     servtab = sep;
  634.     sigsetmask(omask);
  635.     return (sep);
  636. }
  637.  
  638. FILE    *fconfig = NULL;
  639. struct    servtab serv;
  640. char    line[256];
  641. char    *skip(), *nextline();
  642.  
  643. setconfig()
  644. {
  645.  
  646.     if (fconfig != NULL) {
  647.         fseek(fconfig, 0L, L_SET);
  648.         return (1);
  649.     }
  650.     fconfig = fopen(CONFIG, "r");
  651.     return (fconfig != NULL);
  652. }
  653.  
  654. endconfig()
  655. {
  656.  
  657.     if (fconfig == NULL)
  658.         return;
  659.     fclose(fconfig);
  660.     fconfig = NULL;
  661. }
  662.  
  663. struct servtab *
  664. getconfigent()
  665. {
  666.     register struct servtab *sep = &serv;
  667.     char *cp, *arg;
  668.     int argc;
  669.     char    *strdup();
  670.  
  671. more:
  672.     while ((cp = nextline(fconfig)) && *cp == '#')
  673.         ;
  674.     if (cp == NULL)
  675.         return ((struct servtab *)0);
  676.     sep->se_service = strdup(skip(&cp));
  677.     arg = skip(&cp);
  678.     if (strcmp(arg, "stream") == 0)
  679.         sep->se_socktype = SOCK_STREAM;
  680.     else if (strcmp(arg, "dgram") == 0)
  681.         sep->se_socktype = SOCK_DGRAM;
  682.     else if (strcmp(arg, "rdm") == 0)
  683.         sep->se_socktype = SOCK_RDM;
  684.     else if (strcmp(arg, "seqpacket") == 0)
  685.         sep->se_socktype = SOCK_SEQPACKET;
  686.     else if (strcmp(arg, "raw") == 0)
  687.         sep->se_socktype = SOCK_RAW;
  688.     else
  689.         sep->se_socktype = -1;
  690.     sep->se_proto = strdup(skip(&cp));
  691.     arg = skip(&cp);
  692.     sep->se_wait = strcmp(arg, "wait") == 0;
  693.     sep->se_user = strdup(skip(&cp));
  694.     sep->se_server = strdup(skip(&cp));
  695.     if (strcmp(sep->se_server, "internal") == 0) {
  696.         register struct biltin *bi;
  697.  
  698.         for (bi = biltins; bi->bi_service; bi++)
  699.             if (bi->bi_socktype == sep->se_socktype &&
  700.                 strcmp(bi->bi_service, sep->se_service) == 0)
  701.                 break;
  702.         if (bi->bi_service == 0) {
  703.             syslog(LOG_ERR, "internal service %s unknown\n",
  704.                 sep->se_service);
  705.             goto more;
  706.         }
  707.         sep->se_bi = bi;
  708.         sep->se_wait = bi->bi_wait;
  709.     } else
  710.         sep->se_bi = NULL;
  711.     argc = 0;
  712.     for (arg = skip(&cp); cp; arg = skip(&cp))
  713.         if (argc < MAXARGV)
  714.             sep->se_argv[argc++] = strdup(arg);
  715.     while (argc <= MAXARGV)
  716.         sep->se_argv[argc++] = NULL;
  717.     return (sep);
  718. }
  719.  
  720. freeconfig(cp)
  721.     register struct servtab *cp;
  722. {
  723.     int i;
  724.  
  725.     if (cp->se_service)
  726.         free(cp->se_service);
  727.     if (cp->se_proto)
  728.         free(cp->se_proto);
  729.     if (cp->se_user)
  730.         free(cp->se_user);
  731.     if (cp->se_server)
  732.         free(cp->se_server);
  733.     for (i = 0; i < MAXARGV; i++)
  734.         if (cp->se_argv[i])
  735.             free(cp->se_argv[i]);
  736. }
  737.  
  738. char *
  739. skip(cpp)
  740.     char **cpp;
  741. {
  742.     register char *cp = *cpp;
  743.     char *start;
  744.  
  745. again:
  746.     while (*cp == ' ' || *cp == '\t')
  747.         cp++;
  748.     if (*cp == '\0') {
  749.         char c;
  750.  
  751.         c = getc(fconfig);
  752.         ungetc(c, fconfig);
  753.         if (c == ' ' || c == '\t')
  754.             if (cp = nextline(fconfig))
  755.                 goto again;
  756.         *cpp = (char *)0;
  757.         return ((char *)0);
  758.     }
  759.     start = cp;
  760.     while (*cp && *cp != ' ' && *cp != '\t')
  761.         cp++;
  762.     if (*cp != '\0')
  763.         *cp++ = '\0';
  764.     *cpp = cp;
  765.     return (start);
  766. }
  767.  
  768. char *
  769. nextline(fd)
  770.     FILE *fd;
  771. {
  772.     char *cp;
  773.  
  774.     if (fgets(line, sizeof (line), fd) == NULL)
  775.         return ((char *)0);
  776.     cp = index(line, '\n');
  777.     if (cp)
  778.         *cp = '\0';
  779.     return (line);
  780. }
  781.  
  782. char *
  783. strdup(cp)
  784.     char *cp;
  785. {
  786.     char *new;
  787.  
  788.     if (cp == NULL)
  789.         cp = "";
  790.     new = malloc((unsigned)(strlen(cp) + 1));
  791.     if (new == (char *)0) {
  792.         syslog(LOG_ERR, "Out of memory.");
  793.         exit(-1);
  794.     }
  795.     strcpy(new, cp);
  796.     return (new);
  797. }
  798.  
  799. setproctitle(a, s)
  800.     char *a;
  801.     int s;
  802. {
  803.     int size;
  804.     register char *cp;
  805.     struct sockaddr_in sin;
  806.     char buf[80];
  807.  
  808.     cp = Argv[0];
  809.     size = sizeof(sin);
  810.     if (getpeername(s, &sin, &size) == 0)
  811.         sprintf(buf, "-%s [%s]", a, inet_ntoa(sin.sin_addr)); 
  812.     else
  813.         sprintf(buf, "-%s", a); 
  814.     strncpy(cp, buf, LastArg - cp);
  815.     cp += strlen(cp);
  816.     while (cp < LastArg)
  817.         *cp++ = ' ';
  818. }
  819.  
  820. /*
  821.  * Internet services provided internally by inetd:
  822.  */
  823.  
  824. /* ARGSUSED */
  825. echo_stream(s, sep)        /* Echo service -- echo data back */
  826.     int s;
  827.     struct servtab *sep;
  828. {
  829.     char buffer[BUFSIZ];
  830.     int i;
  831.  
  832.     setproctitle("echo", s);
  833.     while ((i = read(s, buffer, sizeof(buffer))) > 0 &&
  834.         write(s, buffer, i) > 0)
  835.         ;
  836.     exit(0);
  837. }
  838.  
  839. /* ARGSUSED */
  840. echo_dg(s, sep)            /* Echo service -- echo data back */
  841.     int s;
  842.     struct servtab *sep;
  843. {
  844.     char buffer[BUFSIZ];
  845.     int i, size;
  846.     struct sockaddr sa;
  847.  
  848.     size = sizeof(sa);
  849.     if ((i = recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size)) < 0) {
  850.         close(s);
  851.         return;
  852.     }
  853.     (void) sendto(s, buffer, i, 0, &sa, sizeof(sa));
  854. }
  855.  
  856. /* ARGSUSED */
  857. discard_stream(s, sep)        /* Discard service -- ignore data */
  858.     int s;
  859.     struct servtab *sep;
  860. {
  861.     char buffer[BUFSIZ];
  862.  
  863.     setproctitle("discard", s);
  864.     while (1) {
  865.         while (read(s, buffer, sizeof(buffer)) > 0)
  866.             ;
  867.         if (errno != EINTR)
  868.             break;
  869.     }
  870.     exit(0);
  871. }
  872.  
  873. /* ARGSUSED */
  874. discard_dg(s, sep)        /* Discard service -- ignore data */
  875.     int s;
  876.     struct servtab *sep;
  877. {
  878.     char buffer[BUFSIZ];
  879.  
  880.     (void) read(s, buffer, sizeof(buffer));
  881. }
  882.  
  883. #include <ctype.h>
  884. #define LINESIZ 72
  885. char ring[128];
  886. char *endring;
  887.  
  888. initring()
  889. {
  890.     register int i;
  891.  
  892.     endring = ring;
  893.  
  894.     for (i = 0; i <= 128; ++i)
  895.         if (isprint(i))
  896.             *endring++ = i;
  897. }
  898.  
  899. /* ARGSUSED */
  900. chargen_stream(s, sep)        /* Character generator */
  901.     int s;
  902.     struct servtab *sep;
  903. {
  904.     char text[LINESIZ+2];
  905.     register int i;
  906.     register char *rp, *rs, *dp;
  907.  
  908.     setproctitle("discard", s);
  909.     if (endring == 0)
  910.         initring();
  911.  
  912.     for (rs = ring; ; ++rs) {
  913.         if (rs >= endring)
  914.             rs = ring;
  915.         rp = rs;
  916.         dp = text;
  917.         i = MIN(LINESIZ, endring - rp);
  918.         bcopy(rp, dp, i);
  919.         dp += i;
  920.         if ((rp += i) >= endring)
  921.             rp = ring;
  922.         if (i < LINESIZ) {
  923.             i = LINESIZ - i;
  924.             bcopy(rp, dp, i);
  925.             dp += i;
  926.             if ((rp += i) >= endring)
  927.                 rp = ring;
  928.         }
  929.         *dp++ = '\r';
  930.         *dp++ = '\n';
  931.  
  932.         if (write(s, text, dp - text) != dp - text)
  933.             break;
  934.     }
  935.     exit(0);
  936. }
  937.  
  938. /* ARGSUSED */
  939. chargen_dg(s, sep)        /* Character generator */
  940.     int s;
  941.     struct servtab *sep;
  942. {
  943.     char text[LINESIZ+2];
  944.     register int i;
  945.     register char *rp;
  946.     static char *rs = ring;
  947.     struct sockaddr sa;
  948.     int size;
  949.  
  950.     if (endring == 0)
  951.         initring();
  952.  
  953.     size = sizeof(sa);
  954.     if (recvfrom(s, text, sizeof(text), 0, &sa, &size) < 0) {
  955.         close(s);
  956.         return;
  957.     }
  958.     rp = rs;
  959.     if (rs++ >= endring)
  960.         rs = ring;
  961.     i = MIN(LINESIZ - 2, endring - rp);
  962.     bcopy(rp, text, i);
  963.     if ((rp += i) >= endring)
  964.         rp = ring;
  965.     if (i < LINESIZ - 2) {
  966.         bcopy(rp, text, i);
  967.         if ((rp += i) >= endring)
  968.             rp = ring;
  969.     }
  970.     text[LINESIZ - 2] = '\r';
  971.     text[LINESIZ - 1] = '\n';
  972.  
  973.     (void) sendto(s, text, sizeof(text), 0, &sa, sizeof(sa));
  974. }
  975.  
  976. /*
  977.  * Return a machine readable date and time, in the form of the
  978.  * number of seconds since midnight, Jan 1, 1900.  Since gettimeofday
  979.  * returns the number of seconds since midnight, Jan 1, 1970,
  980.  * we must add 2208988800 seconds to this figure to make up for
  981.  * some seventy years Bell Labs was asleep.
  982.  */
  983.  
  984. long
  985. machtime()
  986. {
  987.     struct timeval tv;
  988.  
  989.     if (gettimeofday(&tv, (struct timezone *)0) < 0) {
  990.         fprintf(stderr, "Unable to get time of day\n");
  991.         return (0L);
  992.     }
  993.     return (htonl((long)tv.tv_sec + 2208988800));
  994. }
  995.  
  996. /* ARGSUSED */
  997. machtime_stream(s, sep)
  998.     int s;
  999.     struct servtab *sep;
  1000. {
  1001.     long result;
  1002.  
  1003.     result = machtime();
  1004.     (void) write(s, (char *) &result, sizeof(result));
  1005. }
  1006.  
  1007. /* ARGSUSED */
  1008. machtime_dg(s, sep)
  1009.     int s;
  1010.     struct servtab *sep;
  1011. {
  1012.     long result;
  1013.     struct sockaddr sa;
  1014.     int size;
  1015.  
  1016.     size = sizeof(sa);
  1017.     if (recvfrom(s, (char *)&result, sizeof(result), 0, &sa, &size) < 0) {
  1018.         close(s);
  1019.         return;
  1020.     }
  1021.     result = machtime();
  1022.     (void) sendto(s, (char *) &result, sizeof(result), 0, &sa, sizeof(sa));
  1023. }
  1024.  
  1025. /* ARGSUSED */
  1026. daytime_stream(s, sep)        /* Return human-readable time of day */
  1027.     int s;
  1028.     struct servtab *sep;
  1029. {
  1030.     char buffer[256];
  1031.     time_t time(), clock;
  1032.     char *ctime();
  1033.  
  1034.     clock = time((time_t *) 0);
  1035.  
  1036.     sprintf(buffer, "%s\r", ctime(&clock));
  1037.     (void) write(s, buffer, strlen(buffer));
  1038. }
  1039.  
  1040. /* ARGSUSED */
  1041. daytime_dg(s, sep)        /* Return human-readable time of day */
  1042.     int s;
  1043.     struct servtab *sep;
  1044. {
  1045.     char buffer[256];
  1046.     time_t time(), clock;
  1047.     struct sockaddr sa;
  1048.     int size;
  1049.     char *ctime();
  1050.  
  1051.     clock = time((time_t *) 0);
  1052.  
  1053.     size = sizeof(sa);
  1054.     if (recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size) < 0) {
  1055.         close(s);
  1056.         return;
  1057.     }
  1058.     sprintf(buffer, "%s\r", ctime(&clock));
  1059.     (void) sendto(s, buffer, strlen(buffer), 0, &sa, sizeof(sa));
  1060. }
  1061.  
  1062. /*
  1063.  * print_service:
  1064.  *    Dump relevant information to stderr
  1065.  */
  1066. print_service(action, sep)
  1067.     char *action;
  1068.     struct servtab *sep;
  1069. {
  1070.     fprintf(stderr,
  1071.         "%s: %s proto=%s, wait=%d, user=%s builtin=%x server=%s\n",
  1072.         action, sep->se_service, sep->se_proto,
  1073.         sep->se_wait, sep->se_user, sep->se_bi, sep->se_server);
  1074. }
  1075. @
  1076.  
  1077.  
  1078. 1.11
  1079. log
  1080. @pass SPRITE_OS variable to children
  1081. @
  1082. text
  1083. @d770 4
  1084. a773 2
  1085.     if ((i = recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size)) < 0)
  1086.         return;
  1087. d875 4
  1088. a878 2
  1089.     if (recvfrom(s, text, sizeof(text), 0, &sa, &size) < 0)
  1090.         return;
  1091. d938 4
  1092. a941 2
  1093.     if (recvfrom(s, (char *)&result, sizeof(result), 0, &sa, &size) < 0)
  1094.         return;
  1095. d975 4
  1096. a978 2
  1097.     if (recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size) < 0)
  1098.         return;
  1099. @
  1100.  
  1101.  
  1102. 1.10
  1103. log
  1104. @pass limited environment to children
  1105. @
  1106. text
  1107. @d169 1
  1108. a169 1
  1109.      * Get the "true" environment and pull out the two variables
  1110. d174 1
  1111. @
  1112.  
  1113.  
  1114. 1.9
  1115. log
  1116. @get rid of cc complaints about void declarations
  1117. @
  1118. text
  1119. @d162 4
  1120. d167 23
  1121. d360 1
  1122. a360 1
  1123.                 execv(sep->se_server, sep->se_argv);
  1124. @
  1125.  
  1126.  
  1127. 1.8
  1128. log
  1129. @make process id be a full int!!
  1130. @
  1131. text
  1132. @d85 1
  1133. a85 1
  1134. int    reapchild(), retry();
  1135. d346 1
  1136. d379 1
  1137. d460 1
  1138. @
  1139.  
  1140.  
  1141. 1.7
  1142. log
  1143. @Error check was in wrong place; caused abort after 25 connections.
  1144. @
  1145. text
  1146. @d100 2
  1147. a101 2
  1148.     short    se_wait;        /* single threaded server */
  1149.     short    se_checked;        /* looked at during merge */
  1150. d121 2
  1151. a122 2
  1152.     short    bi_fork;        /* 1 if should fork before call */
  1153.     short    bi_wait;        /* 1 if should wait for child */
  1154. @
  1155.  
  1156.  
  1157. 1.6
  1158. log
  1159. @Changed config file to default to /sprite/daemons/inetd.conf. Handle 
  1160. death of the ipServer.
  1161. @
  1162. text
  1163. @d220 9
  1164. a228 2
  1165.             if (n < 0 && errno != EINTR)
  1166.                 syslog(LOG_WARNING, "select: %m\n");
  1167. a229 5
  1168.             selectErrors++;
  1169.             if (selectErrors > 25) {
  1170.             syslog(LOG_ERR, "Exiting: Too many select errors\n");
  1171.             exit(1);
  1172.             }
  1173. @
  1174.  
  1175.  
  1176. 1.5
  1177. log
  1178. @Converted to use new libc.a.
  1179. @
  1180. text
  1181. @d76 1
  1182. d148 1
  1183. a148 1
  1184. char    *CONFIG = "/etc/inetd.conf";
  1185. d161 1
  1186. d223 5
  1187. d232 1
  1188. a232 1
  1189.         if (FD_ISSET(sep->se_fd, &readable)) {
  1190. @
  1191.  
  1192.  
  1193. 1.4
  1194. log
  1195. @Defined some things that should have been defined in a header file
  1196. but we seem to have the sun header rather than 4.3.
  1197. @
  1198. text
  1199. @d3 8
  1200. a10 2
  1201.  * All rights reserved.  The Berkeley software License Agreement
  1202.  * specifies the terms and conditions for redistribution.
  1203. a81 19
  1204. /*
  1205.  * This is defined in types.h under 4.3.  Why is it even used here?
  1206.  */
  1207. #define    NBBY    8        /* number of bits in a byte */
  1208. /*
  1209.  * Select uses bit masks of file descriptors in longs.
  1210.  * These macros manipulate such bit fields (the filesystem macros use chars).
  1211.  */
  1212. typedef long    fd_mask;
  1213. #define NFDBITS    (sizeof(fd_mask) * NBBY)    /* bits per mask */
  1214.  
  1215. #define    FD_SET(n, p)    ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
  1216. #define    FD_CLR(n, p)    ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
  1217. #define    FD_ISSET(n, p)    ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
  1218.  
  1219. /*
  1220.  * ** end of 4.3 addition 
  1221.  */
  1222.  
  1223. d550 1
  1224. @
  1225.  
  1226.  
  1227. 1.3
  1228. log
  1229. @fixed error handling for accepts. now removes socket.
  1230. @
  1231. text
  1232. @d76 19
  1233. @
  1234.  
  1235.  
  1236. 1.2
  1237. log
  1238. @made changes necessary to run under ipServer.
  1239. @
  1240. text
  1241. @d204 1
  1242. a204 1
  1243.         int s, ctrl, n;
  1244. d217 1
  1245. d231 6
  1246. a236 1
  1247.                 syslog(LOG_WARNING, "accept: %m");
  1248. @
  1249.  
  1250.  
  1251. 1.1
  1252. log
  1253. @Initial revision
  1254. @
  1255. text
  1256. @a53 1
  1257. #include <sys/ioctl.h>
  1258. d180 10
  1259. a189 6
  1260. #ifndef DEBUG
  1261.     if (fork())
  1262.         exit(0);
  1263.     { int s;
  1264.     for (s = 0; s < 10; s++)
  1265.         (void) close(s);
  1266. a190 10
  1267.     (void) open("/", O_RDONLY);
  1268.     (void) dup2(0, 1);
  1269.     (void) dup2(0, 2);
  1270.     { int tt = open("/dev/tty", O_RDWR);
  1271.       if (tt > 0) {
  1272.         ioctl(tt, TIOCNOTTY, (char *)0);
  1273.         close(tt);
  1274.       }
  1275.     }
  1276. #endif
  1277. d202 1
  1278. d239 2
  1279. a284 8
  1280. #ifdef    DEBUG
  1281.             int tt;
  1282.  
  1283.             if (dofork && (tt = open("/dev/tty", O_RDWR)) > 0) {
  1284.                 ioctl(tt, TIOCNOTTY, 0);
  1285.                 close(tt);
  1286.             }
  1287. #endif
  1288. d310 2
  1289. a311 2
  1290.                     fprintf(stderr, "%d execl %s\n",
  1291.                         getpid(), sep->se_server);
  1292. d331 2
  1293. d353 2
  1294. @
  1295.